﻿Imports System.Runtime.Serialization
Imports System.Xml.Serialization
Imports System.Runtime.Serialization.Json
Imports Runa.Common.Helper

Namespace Runtime

    Namespace Serialization

        Public Enum SerializationType As Integer
            XML = 0
            Binary = 1
            Json = 2
        End Enum

        Public NotInheritable Class Serializer

            Public Property Type() As SerializationType

            Public Shared Property XmlSerializer() As New Serializer(SerializationType.XML)
            Public Shared Property JsonSerializer() As New Serializer(SerializationType.Json)

#If Windows And (Not NETFX_CORE) Then
            Public Shared Property BinarySerializer() As New Serializer(SerializationType.Binary)
#End If

            Public Sub New(Optional ByVal t As SerializationType = SerializationType.XML)
                Me.Type = t
            End Sub

            Public Function Serialize(Of T)(ByVal obj As T) As MemoryStream
                Select Case Me.Type
                    Case SerializationType.XML
                        Dim ms As New System.IO.MemoryStream()
                        Dim xs As New XmlSerializer(obj.GetType())
                        xs.Serialize(ms, obj)
                        Return ms
                    Case SerializationType.Binary
#If WINDOWS And (Not NETFX_CORE) Then
                        Dim SFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
                        Dim ms As New System.IO.MemoryStream()
                        SFormatter.Serialize(ms, obj)
                        Return ms
#Else
                        Throw New NotSupportedException("Binary serialization is not supported on this platform.")
#End If
                    Case SerializationType.Json
                        Dim ser As New DataContractJsonSerializer(GetType(T))
                        Dim ms As New MemoryStream()
                        ser.WriteObject(ms, obj)
                        Return ms
                    Case Else
                        Throw New ArgumentException("Invalid serialization type.")
                End Select
            End Function

            Public Function Deserialize(Of T)(ByVal data() As Byte) As T
                Using ms As New MemoryStream(data)
                    Return Me.Deserialize(Of T)(ms)
                End Using
            End Function

            Public Function Deserialize(Of T)(ByVal stream As Stream) As T
                Select Case Me.Type
                    Case SerializationType.XML
                        Dim xs As New XmlSerializer(GetType(T))
                        Return GenericCast(Of Object, T)(xs.Deserialize(stream))
                    Case SerializationType.Binary
#If Windows And (Not NETFX_CORE) Then
                        Dim SFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
                        Dim Obj As T = SFormatter.Deserialize(stream)
                        Return Obj
#Else
                        Throw New NotSupportedException("Binary serialization is not supported on this platform.")
#End If
                    Case SerializationType.Json
                        Dim ser As New DataContractJsonSerializer(GetType(T))
                        Dim obj = GenericCast(Of Object, T)(ser.ReadObject(stream))
                        Return obj
                    Case Else
                        Throw New ArgumentException("Invalid serialization type.")
                End Select
            End Function

        End Class

    End Namespace

End Namespace